/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "i2c.h"
#include "rtc.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "myradio.h"
#include "sht30.h"
#include "flash.h"
#include "ble.h"
#include "myaes.h"
#include "secret.h"
#include "conf.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
#define ADC_LEN 6
#define VREFINT_CAL      (*(uint16_t*)VREFINT_CAL_ADDR) //Vrefint???ADC?
uint32_t channels[ADC_LEN] = {ADC_CHANNEL_VREFINT, ADC_CHANNEL_0, ADC_CHANNEL_8, ADC_CHANNEL_9, ADC_CHANNEL_10, ADC_CHANNEL_11};
int16_t adcs[ADC_LEN] = {0};
static void GetVols(int16_t values[]);
static struct THData thData;
extern struct LoraRespData loraRespData;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
extern void ExampleSX126xReciveDemo(void);
static void FillLoraData(struct LoraRespData *data, struct THData *th, int16_t adcs[], uint16_t);
static void aes_ecb_example(void);
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  MX_TIM14_Init();
  MX_ADC1_Init();
  MX_I2C1_Init();
  MX_RTC_Init();
  /* USER CODE BEGIN 2 */
	HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
	uart2registerIdleCallback();
	HAL_TIM_Base_Start_IT(&htim14);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	PrintResetReason();
	if (TYPE == NBAT_TYPE) {
		EnableBLE();
		HAL_Delay(500);
		BleInit();
	} else if(TYPE == BAT_TYPE) {
		if(!TimerWakeUPReboot())  {
			EnableBLE();
			HAL_Delay(500);
			BleInit();
			HAL_Delay(10 * 1000);
		}
	}
	
	// DEFAULT ENABLE NTC and TH
	EnableTHandNTC();
	
	struct FlashData *conf = GET_FLASH_DATA();
	if (conf== NULL) {
		LoraInit(0,0,0,0, 9, 1);
	} else {
		printf("server: %s self: %s f:%d b:%d n:%d p:%d secret:[%s]\r\n", conf->srvName, conf->self, conf->freq, conf->baud, conf->net, conf->power, conf->secret);
		LoraInit(conf->freq, conf->baud, conf->net, conf->power, conf->sf, conf->cr);
	}
	HAL_Delay(100);
	
	uint32_t counter = 0;
	uint8_t dataOK = 0;
	HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		//HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		//printf("Task is running ...\r\n");
		//HAL_Delay(1000);
		//ExampleSX126xReciveDemo();
		struct FlashData *conf = GET_FLASH_DATA();
		//non-server shinning quick
		if((counter % 100) == 0 && (conf == NULL || ((conf != NULL) && strlen(conf->srvName) < 5))) {
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
	  // every thing is ok shinning.
		}
		if((counter % 10000)==0) {
			GetVols(adcs);
			//printf("ad0: %d, ad1: %d, ad2: %d, ad3: %d, ad4: %d\r\n", adcs[0], adcs[1], adcs[2], adcs[3], adcs[4]);
			memset(&thData, 0, sizeof(thData));
			GET_STH30_DATA(&thData);
			if(conf != NULL && conf->th != 1 && thData.err == 0) {
				FlashSetTHConf(1);
			}
			printf("conf->th: %d, temp:%d  humi:%d thErr:%d \r\n",conf->th, thData.Temp, thData.Humi, thData.err);
			//if(conf != NULL && conf->th == 1 && thData.err == 0) {
			//	HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
			//}
			//printf("ERR:%d, temp: %d, humi: %d\r\n", thData.err, thData.Temp, thData.Humi);
			//printf("LORA data size: %d\r\n", sizeof(struct LoraRespData));
			FillLoraData(&loraRespData, &thData, adcs, 0);
			printf("OK....\r\n");
			dataOK = 1;
			//aes_ecb_example();
			//char *input = "1234567890";
			//char output[17] = {0};
			//generatePassword(input, output);
			//printf("[%s]\r\n", output);
			//for(int i=0;i<32;i++) {
			//	printf("%X", output[i]);
			//}
			//printf("\r\n");
		}
		
		// sht30 error shinning not slow not fast
		
		if((counter % 1000) ==0 && conf != NULL && conf->th == 1) {
			if(thData.err != 0) {
				printf("thErr 0:%d\r\n", thData.err);
				HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
			} else {
				HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
			}
		}
		
		if(conf != NULL && strlen(conf->srvName)>0 && dataOK == 1) {
			int ret = ProcessRadio(&loraRespData, conf, TYPE);
			//printf("RET: %d\r\n");
			if(TYPE == BAT_TYPE && ret > 0) {
				HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, ret, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
				EnterSTANDBYMode();
				//printf("Enter stop mode ..\r\n");
				//HAL_Delay(5000);
			}
		}
		
		if(TYPE == NBAT_TYPE) {
			uart2DataHandle();
		} else if(TYPE == BAT_TYPE) {
			if(!TimerWakeUPReboot()) {
				uart2DataHandle();
			}
		}
		
		counter = counter + 1;
		HAL_Delay(1);
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Configure LSE Drive Capability
  */
  HAL_PWR_EnableBkUpAccess();
  __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSE;
  RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
  RCC_OscInitStruct.PLL.PLLN = 8;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */
int fputc(int ch, FILE *fp)
{
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xff);
	return ch;
}

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(huart == &huart2) {
		uart2IdleCallback(Size);
	}
	printf("huart2 size: %d\r\n", Size);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)	
{
	if(htim == &htim14) {
		Radio_Timer_IRQHandler();
	}
}

void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
	if (GPIO_Pin == RADIO_DIO1_Pin) {
		DIO_IRQHandler();
	}
  /* Prevent unused argument(s) compilation warning */
  //UNUSED(GPIO_Pin);

  /* NOTE: This function should not be modified, when the callback is needed,
           the HAL_GPIO_EXTI_Rising_Callback could be implemented in the user file
   */
}

static uint16_t GetAdc(uint32_t ch, int times)   
{	
		HAL_ADCEx_Calibration_Start(&hadc1);
		//while(HAL_ADCEx_Calibration_Start(&hadc1)!=HAL_OK){};
    ADC_ChannelConfTypeDef sConfig;    
    sConfig.Channel=ch;                                   //??
    sConfig.Rank=ADC_REGULAR_RANK_1;                                       //?1???,??1
    sConfig.SamplingTime=ADC_SAMPLETIME_160CYCLES_5;        //????
    HAL_ADC_ConfigChannel(&hadc1,&sConfig);        //?????
    //HAL_ADC_Start(&hadc1);                               //??ADC	
    //HAL_ADC_PollForConversion(&hadc1,10);  
		HAL_Delay(10);
		uint32_t value_sum=0;	
		uint8_t i;
		
		for(i=0;i<times;i++)
		{
			HAL_ADC_Start(&hadc1);								//????
			HAL_ADC_PollForConversion(&hadc1,0xFF);	
			
			value_sum += HAL_ADC_GetValue(&hadc1);				//??					
			
			HAL_ADC_Stop(&hadc1);								//????
		}
		//HAL_Delay(500);
		return value_sum/times;									//?????
	//???? 
	//return (uint16_t)HAL_ADC_GetValue(&hadc1);	        //??????ADC1????????
}

static void GetVols(int16_t values[])
{
	uint16_t adc = GetAdc(channels[0], 10);
	int VDDA =(int)(3.f*1000*(float)(VREFINT_CAL)/(float)(adc));
	values[0] = VDDA;
	printf("\r\nVDDA: %d\r\n", VDDA);
	for(int i=1; i<ADC_LEN; i++) {
		adc = GetAdc(channels[i], 10);
		values[i] = VDDA * adc / 4095;
		printf("adcs: %d, value: %d\r\n",i, values[i]);
	}
}

static void FillLoraData(struct LoraRespData*data, struct THData *th, int16_t adcs[], uint16_t bat)
{
	//data->serve[0] = 1;
	data->temp = th->Temp;
	data->humi = th->Humi;
	data->thErr = th->err;
	data->bat = bat;
	for(int i=0;i<ADC_LEN;i++) {
		data->adcs[i] = adcs[i];
	}
}


static void aes_ecb_example(void) 
{
    // 1. ???????
    const char *plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    size_t plaintext_len = strlen(plaintext);
    
    // AES-128?? (16??)
    unsigned char key[16] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
    };
    
    // 2. ??
    unsigned char ciphertext[128]; // ???????
    size_t ciphertext_len;
    
    int ret = aes_128_ecb_encrypt(key, 
                                 (unsigned char *)plaintext, plaintext_len,
                                 ciphertext, &ciphertext_len);
    
    if(ret != 0) {
        printf("encrypt failed: %d\r\n", ret);
        return;
    }
		printf("\r\n");
    for(int i=0;i<ciphertext_len;i++) {
			printf("%x",ciphertext[i]);
		}
		printf("\r\n");
    printf("encrypt succeed: %lu\r\n", ciphertext_len);
    
    // 3. ??
    unsigned char decrypted[128];
    size_t decrypted_len;
    
    ret = aes_128_ecb_decrypt(key, 
                             ciphertext, ciphertext_len,
                             decrypted, &decrypted_len);
    
    if(ret != 0) {
        printf("decrypt failed: %d\r\n", ret);
        return;
    }
    
    // 4. ????
    if(decrypted_len == plaintext_len && 
       memcmp(plaintext, decrypted, plaintext_len) == 0) {
        printf("decrypt succeed: %.*s\r\n", (int)decrypted_len, decrypted);
    } else {
        printf("decrypt failed!\r\n");
    }
}

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
